#include "graphics.opengl/shader.h"

namespace dw
{
	namespace graphics
	{
		namespace opengl
		{

			Shader::Shader(const Type type) : graphics::Shader(type), _glId(0)
			{
			}

			Shader::~Shader()
			{
				unload();
			}

			void Shader::load(std::istream& is)
			{
				GLcharARB* buffer;
				GLint size;

				if (_loaded)
					return ;

				_glId = glCreateShaderObjectARB(getGLType());

				is.seekg(0, std::ios::end);
				size = is.tellg();
				is.seekg(0, std::ios::beg);
				buffer = new GLcharARB[size];
				is.read(buffer, size);
				//buffer[size + 1] = '\0';

				glShaderSourceARB(_glId, 1, (const GLcharARB**)&buffer, &size);

				_loaded = true;
			}

			void Shader::unload()
			{
				if (_loaded)
					glDeleteObjectARB(_glId);
				_loaded = false;
			}

			void Shader::compile()
			{
				int compiled;

				glCompileShaderARB(_glId);
				// DW_INFO << _name	<< std::endl;
				glGetObjectParameterivARB(_glId, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
				//if (!compiled)
				{
					int maxLength;
					char* infoLog;

					glGetObjectParameterivARB(_glId, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength);
					infoLog = new char[maxLength];
					glGetInfoLogARB(_glId, maxLength, &maxLength, infoLog);
					// DW_INFO << infoLog << std::endl;
				}
			}

			void Shader::dispose()
			{
				delete this;
			}

			GLenum Shader::getGLType() const
			{
				switch (_type)
				{
				case VERTEX_SHADER		: return GL_VERTEX_SHADER_ARB;		break ;
				case FRAGMENT_SHADER	: return GL_FRAGMENT_SHADER_ARB;	break ;
				default								: return GL_ZERO;
				}
			}

		} // namespace opengl
	} // namespace graphics
} // namespace dw